#include "utf_check.hpp"
namespace Utf{
  //通过起始字节判断字符长度
  int getByteLength(unsigned char c) {
    if ((c & 0x80) == 0) {  //0xxxxxxx  0x00-0x80
        return 1;
      } else if ((c & 0xE0) == 0xC0) {  //110xxxxx  0xC0-0xDF
        return 2;
      } else if ((c & 0xF0) == 0xE0) {  //1110xxxx  0xE0-0xEF
        return 3;
      } else if ((c & 0xF8) == 0xF0) {  //11110xxx  0xF0-0xF4
         return 4;
      } else {
        // 无效的起始字节 0x80-0xC0
        return 0; 
      }
  }
  //检查是否为合法的后续字节
  bool isContinuationByte(unsigned char c) {
      return (c & 0xC0) == 0x80;
  }
  // 检查码点的有效性
  bool isCodePointValid(uint32_t code_point) {
    // 检查是否在Unicode有效范围内 (0x0000-0x10FFFF)
    if (code_point > 0x10FFFF) {
        return false;
    }
    // 检查是否为代理对的一部分 (U+D800到U+DFFF)
    if (code_point >= 0xD800 && code_point <= 0xDFFF) {
        return false;
    }
    // 检查是否为非字符 (如U+FFFE, U+FFFF等)
    if ((code_point & 0xFFFE) == 0xFFFE) {
        return false;
    }
    return true;
  }
  // 检查编码是否使用了最短字节数（防止过长征码）
  bool isShortestEncoding(uint32_t code_point, int bytes) {
    if (bytes == 1) {
      return code_point <= 0x7F;  // 1字节必须对应U+0000-U+007F
    } else if (bytes == 2) {
      return code_point >= 0x80 && code_point <= 0x7FF;  // 2字节必须对应U+0080-U+07FF
    } else if (bytes == 3) {
      return code_point >= 0x800 && code_point <= 0xFFFF;  // 3字节必须对应U+0800-U+FFFF
    } else if (bytes == 4) {
      return code_point >= 0x10000 && code_point <= 0x10FFFF;  // 4字节必须对应U+10000-U+10FFFF
    }
    return false;
  }
  /*
  *UTF-8的编码规则明显体现在字符的首字节和后续字节
  *对于只有一个字节的符号，字节的第一位设为0
  *对于n字节的符号（n > 1），第一个字节的前n位都设为 1，第n + 1位设为0
  *通过逐字符判断首字节编码和后续字节可以知道是否为UTF-8编码
  *首先判断字符的字节长度
  */
  bool isUTF8(const std::string_view& str) {
    for (size_t i = 0; i < str.length();) {
      unsigned char c = static_cast<unsigned char>(str[i]);
      int bytes = getByteLength(c);
      if (bytes == 0 || i + bytes > str.length()) {
        return false;
      }
      uint32_t code_point;
      /*
      将编码还原为码点值
      1 字节：0xxxxxxx（低 7 位为有效数据）
      2 字节：110xxxxx 10xxxxxx（第一个字节低 5 位 + 第二个字节低 6 位为有效数据）
      3 字节：1110xxxx 10xxxxxx 10xxxxxx（第一个字节低 4 位 + 后两个字节各低 6 位为有效数据）
      4 字节：11110xxx 10xxxxxx 10xxxxxx 10xxxxxx（第一个字节低 3 位 + 后三个字节各低 6 位为有效数据）
      */
      switch (bytes)
      {
        case 1:
          code_point = c;
          break;
        case 2:
          code_point = ((c & 0x1F) << 6) | (static_cast<unsigned char>(str[i+1]) & 0x3F);
          break;
        case 3:
          code_point = ((c & 0x0F) << 12) | ((static_cast<unsigned char>(str[i+1]) & 0x3F) << 6)
                                            | (static_cast<unsigned char>(str[i+2]) & 0x3F);
          break;
        case 4:
          code_point = ((c & 0x07) << 18) | ((static_cast<unsigned char>(str[i+1]) & 0x3F) << 12)
                                            | ((static_cast<unsigned char>(str[i+2] & 0x3F)) << 6)
                                              | (static_cast<unsigned char>(str[i+3] & 0x3F));
          break;     
        default:
          return false;
      } 
      if (!isCodePointValid(code_point) || !isShortestEncoding(code_point, bytes)) {return false;}
      // 检查后续字节是否符合格式
      for (int j = 1; j < bytes; ++j) {
        unsigned char nextByte = static_cast<unsigned char>(str[i + j]);
        if (!isContinuationByte(nextByte)) {
            return false;
        }
      }
      
    i += bytes;
    }
    return true;
  }

}//namespace Utf
// 鏈夋晥娴嬭瘯鐢ㄤ緥
/*int main(){
  using namespace Utf;
  assert(isUTF8("Hello, world!") == true);
  assert(isUTF8("浣犲ソ锛屼笘鐣�") == true);
  assert(isUTF8("馃榾馃憤") == true);
  assert(isUTF8("馉湈") == true);
  assert(isUTF8("漏庐鈩�") == true);
  
  // 鏃犳晥娴嬭瘯鐢ㄤ緥
  assert(isUTF8("\x80") == false);
  assert(isUTF8("\xC2") == false);
  assert(isUTF8("\xC2\xFF") == false);
  assert(isUTF8("\xC0\xAF") == false);
  assert(isUTF8("\xED\xA0\x80") == false);
  assert(isUTF8("\xF4\x90\x80\x80") == false);
  
  // 杈圭晫娴嬭瘯鐢ㄤ緥
  assert(isUTF8("") == true);
  assert(isUTF8("\x7F") == true);
  
  std::cout << "鎵€鏈夋祴璇曠敤渚嬮€氳繃锛�" << std::endl;
  return 0;
}*/
  
/* int main() {
  using namespace Utf;
  
    assert(isUTF8("Hello, world!") == true); 
    assert(isUTF8("浣犲ソ锛屼笘鐣岋紒") == true);         
    assert(isUTF8("馃榾") == true);        
    assert(isUTF8("\xC0\xAF") == false);  
    assert(isUTF8("\xE0\x80\x20") == false);     
           
  
  std::cout << "鎵€鏈夋祴璇曠敤渚嬮€氳繃锛�" << std::endl;
  return 0;
} */
/* int main() {
    //绌哄瓧绗︿覆
    bool isutf = Utf::isUTF8("");
    std::cout << (isutf ? "yes" : "no") << std::endl;

    //ASCII瀛楃
    isutf = Utf::isUTF8("Hello, world!");
    std::cout << (isutf ? "yes" : "no") << std::endl;

    //涓ゅ瓧鑺俇TF-8瀛楃
    isutf = Utf::isUTF8("\xC3\xA9");  // 茅
    std::cout << (isutf ? "yes" : "no") << std::endl;

    //涓夊瓧鑺俇TF-8瀛楃
    isutf = Utf::isUTF8("\xce\xa0");  
    std::cout << (isutf ? "yes" : "no") << std::endl;

    //鍥涘瓧鑺俇TF-8瀛楃
    isutf = Utf::isUTF8("\xF0\x9F\x98\x84"); 
    std::cout << (isutf ? "yes" : "no") << std::endl;
    return 0;
} */
